home *** CD-ROM | disk | FTP | other *** search
- /*
- File: LowerToUpperCase.c
-
- Contains: Source to a FAT extension translator that converts from lower to upper case
- The source type is always 'TEXT' and the destination type is 'UPPR'.
-
- Copyright: © 1994 by Apple Computer, Inc., all rights reserved.
-
-
- Modified from LowerToUpperCaseScrap example. Filled in the file translation part.
- R.Silva 9/11/95
- */
-
- #include <Types.h>
- #include <Files.h>
- #include <MixedMode.h>
- #include <Traps.h>
- #include <Errors.h>
- #include <Memory.h>
- #include <Resources.h>
- #include <Components.h>
- #include <TranslationExtensions.h>
- #include "LowerToUpperCase.h"
-
- //___________________________________________________________________________________________________________
- //
- // Structures
- //
-
- // Our magic cookie to tell if our translation list is initialized or not
- #define kModificationDateMagicCookie 0x00000001
-
- // Set up a fixed scrap translation list structure for easy access
- #if defined(powerc) || defined (__powerc)
- #pragma options align=mac68k
- #endif
- struct OurScrapTranslationList
- {
- unsigned long modDate;
- unsigned long groupCount;
- unsigned long sourceCount;
- unsigned long sourceEntrySize;
- ScrapTypeSpec sourceType;
- unsigned long destinationCount;
- unsigned long destinationEntrySize;
- ScrapTypeSpec desinationType;
- };
- #if defined(powerc) || defined(__powerc)
- #pragma options align=reset
- #endif
-
- typedef struct OurScrapTranslationList OurScrapTranslationList;
- typedef OurScrapTranslationList *OurScrapTranslationListPtr, **OurScrapTranslationListHandle;
-
-
- // Set up a fixed file translation list structure for easy access
- #if defined(powerc) || defined (__powerc)
- #pragma options align=mac68k
- #endif
- struct OurFileTranslationList
- {
- unsigned long modDate;
- unsigned long groupCount;
- unsigned long sourceCount;
- unsigned long sourceEntrySize;
- FileTypeSpec sourceType;
- unsigned long destinationCount;
- unsigned long destinationEntrySize;
- FileTypeSpec desinationType;
- };
- #if defined(powerc) || defined(__powerc)
- #pragma options align=reset
- #endif
-
- typedef struct OurFileTranslationList OurFileTranslationList;
- typedef OurFileTranslationList *OurFileTranslationListPtr, **OurFileTranslationListHandle;
-
-
-
- //___________________________________________________________________________________________________________
- //
- // DoGetScrapTranslationList
- //
- // This routine is called by the Translation Manager when it needs to find out what formats the scrap
- // translator translates between.
- //
- // Enter: self Instance of this translator
- // list Handle to scrap translation list provided by this translator earlier, or empty handle
- // if never set before
- //
- // Exit: list Handle to scrap translation list filled in my this routine
- // returns Any errors that might occur
- //
- pascal ComponentResult DoGetScrapTranslationList(ComponentInstance self,
- ScrapTranslationListHandle list)
- {
- #pragma unused(self)
- OurScrapTranslationListHandle ourList = (OurScrapTranslationListHandle) list; // Easier to reference
- OSErr result = noErr;
-
- // The list never changes here - so see if it's been initialized once by looking
- // for our magic cookie
- if (((*ourList)->modDate) != kModificationDateMagicCookie){
- // Resize the handle to fit our entry
- SetHandleSize((Handle)ourList, sizeof(OurScrapTranslationList));
- if ((result = MemError()) == noErr) {
- // Stuff all the values into our fixed list
- (*ourList)->modDate = kModificationDateMagicCookie; // Magic cookie
- (*ourList)->groupCount = 1; // Number groups = 1
- (*ourList)->sourceCount = 1; // Only 1 source type
- (*ourList)->sourceEntrySize = sizeof(ScrapTypeSpec); // Currently always sizeof(ScrapTypeSpec)
- (*ourList)->sourceType.format = 'TEXT'; // Source type is always 'TEXT'
- (*ourList)->sourceType.hint = 0; // Don't care about this
- (*ourList)->destinationCount = 1; // Only 1 destination type
- (*ourList)->destinationEntrySize = sizeof(ScrapTypeSpec); // Currently always sizeof(ScrapTypeSpec)
- (*ourList)->desinationType.format = 'UPPR'; // Destination type is always 'UPPR'
- (*ourList)->desinationType.hint = 0; // Don't care about this
- }
- }
-
- return result;
- }
-
- //___________________________________________________________________________________________________________
- //
- // DoIdentifyScrap
- //
- // This routine is called to identify a scraps contents. In this case, just check to see if the scrap
- // is type TEXT, and if it is, then we know it's TEXT.
- //
- // Enter: self Instance of this translator
- // dataPtr Pointer to data to identify
- // dataLength Size of data referenced by dataPtr
- // dataFormat Provided format for the data referenced by dataPtr
- //
- // Exit: dataFormat Changed format (if applicable)
- // returns noErr is scrap contents are TEXT, otherwise noTypeErr
- //
- pascal ComponentResult DoIdentifyScrap(ComponentInstance self,
- const void* dataPtr,
- Size dataLength,
- ScrapType* dataFormat)
- {
- #pragma unused(self)
- #pragma unused(dataPtr)
- #pragma unused(dataLength)
- OSErr result = noErr;
-
- // We only know TEXT. See if the format is that. If it isn't then we don't translate
- if (*dataFormat != 'TEXT')
- result = noTypeErr;
-
- return result;
- }
-
- //___________________________________________________________________________________________________________
- //
- // DoTranslateScrap
- //
- // This routine is called to perform a scrap translation. It is only called if the source type is TEXT and
- // if DoIdentifyScrap was called as was able to confirm that. Also, it is only called if the destination type
- // is UPPR.
- //
- // This specific translation converts all lower case characters to upper case. Leaves the rest alone.
- //
- // Enter: self Instance of this translator
- // progressRefNum Reference number to progress dialog
- // srcDataPtr Pointer to source data
- // srcDataLength Length of data pointed to by srcDataPtr
- // srcType Type of data pointed to by srcDataPtr (provided via DoIdentifyScrap)
- // srcTypeHint Hint for data pointed to by srcDataPtr (from ScrapTranslationList)
- // dstData Handle to place translated destination data into
- // dstType Type of data to translate srcDataPtr into
- // dstTypeHint Hint for data to translate to (from ScrapTranslationList)
- //
- // Exit: dstData Handle resized and filled in with translated contents
- // returns Any errors that might occur.
- //
- pascal ComponentResult DoTranslateScrap(ComponentInstance self,
- TranslationRefNum progressRefNum,
- const void* srcDataPtr,
- Size srcDataLength,
- ScrapType srcType,
- long srcTypeHint,
- Handle dstData,
- ScrapType dstType,
- long dstTypeHint)
- {
- #pragma unused(self)
- #pragma unused(srcType)
- #pragma unused(srcTypeHint)
- #pragma unused(dstType)
- #pragma unused(dstTypeHint)
-
- OSErr result;
- char* currentCharacter;
- char* lastCharacter;
- char* writeCharacter;
- short count;
- Boolean canceled = false;
- short myShort;
- Handle myAdvert;
- OSErr myErr;
-
- myShort = OpenComponentResFile((Component)self);
- myAdvert = Get1Resource('PICT', kProgressAdvertisement);
- if(myAdvert != nil){
- DetachResource(myAdvert);
- SetTranslationAdvertisement(progressRefNum,(PicHandle) myAdvert);
- }
- else {
- SetTranslationAdvertisement(progressRefNum, nil);
- }
- myErr = CloseComponentResFile(myShort);
-
- // Resize the destination handle to fit all the translated contents
- SetHandleSize(dstData, srcDataLength);
- if ((result = MemError()) == noErr)
- {
- // Give me a pointer to the first character and the last character in the source buffer
- currentCharacter = (char*) srcDataPtr;
- lastCharacter = currentCharacter + srcDataLength;
-
- // Give me a pointer to the first character in the destination buffer
- // (lock it down first because stupid update may move memory)
- HLock(dstData);
- writeCharacter = (char *)*dstData;
-
- // Keep a count for the progress dialog
- count = 0;
-
- // Loop through each of the characters in the buffer
- while ((currentCharacter <= lastCharacter) && !canceled)
- {
- // Are we in the lower case ASCII range?
- if (('a' <= *currentCharacter) && (*currentCharacter <= 'z'))
- {
- *writeCharacter = (*currentCharacter - ('a' - 'A'));
- }
- else
- *writeCharacter = *currentCharacter;
-
- // Increment the progress bar
- UpdateTranslationProgress(progressRefNum, ++count * (100.00 / srcDataLength), &canceled);
-
- // Next…
- currentCharacter++;
- writeCharacter++;
- }
-
- // Let it wiggle, see it squiggle
- HUnlock(dstData);
- }
-
- return result;
- }
-
- //___________________________________________________________________________________________________________
- //
- // DoGetFileTranslationList
- //
- // This routine is called by the Translation Manager when it needs to find out what formats the scrap
- // translator translates between.
- //
- // Enter: self Instance of this translator
- // list Handle to file translation list provided by this translator earlier, or empty handle
- // if never set before
- //
- // Exit: list Handle to file translation list filled in my this routine
- // returns Any errors that might occur
- //
- //
- pascal ComponentResult DoGetFileTranslationList(ComponentInstance self,
- FileTranslationListHandle list)
- {
- #pragma unused(self)
- #pragma unused(translationList)
-
- OurFileTranslationListHandle ourList = (OurFileTranslationListHandle) list; // Easier to reference
- OSErr result = noErr;
-
- // The list never changes here - so see if it's been initialized once by looking
- // for our magic cookie
- if (((*ourList)->modDate) != kModificationDateMagicCookie){
- // Resize the handle to fit our entry
- SetHandleSize((Handle)ourList, sizeof(OurFileTranslationList));
- if ((result = MemError()) == noErr) {
- // Stuff all the values into our fixed list
- (*ourList)->modDate = kModificationDateMagicCookie; // Magic cookie
- (*ourList)->groupCount = 1; // Number groups = 1
- (*ourList)->sourceCount = 1; // Only 1 source type
- (*ourList)->sourceEntrySize = sizeof(FileTypeSpec); // Currently always sizeof(FileTypeSpec)
- (*ourList)->sourceType.format = 'TEXT'; // Source type is always 'TEXT'
- (*ourList)->sourceType.hint = 0; // Don't care about this
- (*ourList)->sourceType.flags = 0;
- (*ourList)->sourceType.catInfoType = 'TEXT';
- (*ourList)->sourceType.catInfoCreator = 'ttxt';
- (*ourList)->destinationCount = 1; // Only 1 destination type
- (*ourList)->destinationEntrySize = sizeof(FileTypeSpec); // Currently always sizeof(FileTypeSpec)
- (*ourList)->desinationType.format = 'UPPR'; // Destination type is always 'UPPR'
- (*ourList)->desinationType.hint = 0; // Don't care about this
- (*ourList)->desinationType.flags = 0;
- (*ourList)->desinationType.catInfoType = 'UPPR';
- (*ourList)->desinationType.catInfoCreator = 'PPd√'; //??
- }
- }
-
- return result;
- }
-
- //___________________________________________________________________________________________________________
- //
- // DoIdentifyFile
- //
- // This routine is called to identify a file by its contents.
- // Here we simply decide the fileType is 'TEXT'.
- //
- // Enter: self Instance of this translator
- // theDoc file FSSpec
- //
- // Exit: docKind the fileType we decided it was
- // returns noErr
- //
- //
- pascal ComponentResult DoIdentifyFile(ComponentInstance self, const FSSpec *theDoc, FileType *docKind)
- {
- #pragma unused(self)
- #pragma unused(theDoc)
- #pragma unused(docKind)
- OSErr myErr = noErr;
-
- //not doing too much here
-
- *docKind = 'TEXT';
-
- return myErr;
- }
-
- //___________________________________________________________________________________________________________
- //
- // DoTranslateFile
- //
- // This routine is called to perform a file translation. It is only called if the file type is TEXT and
- // if DoIdentifyFile was called as was able to confirm that. Also, it is only called if the destination type
- // is UPPR.
- //
- // This specific translation converts all lower case characters to upper case. Leaves the rest alone.
- //
- // Enter: self Instance of this translator
- // progressRefNum Reference number to progress dialog
- // srcDoc Pointer to source file
- // srcType fileType provided from the DoIdentifyFile
- // srcTypeHint Hint for fileType pointed to by srcDoc (from GetTranslationList)
- // dstDoc Pointer to destination file spec
- // dstType file Type of destination file
- // dstTypeHint Hint for fileType to translate to (from GetTranslationList)
- //
- // Exit: dstDoc File is filled in with translation of data in source file
- // returns Any errors that might occur.
- //
- //
- pascal ComponentResult DoTranslateFile(ComponentInstance self, TranslationRefNum progressRefNum,
- const FSSpec* srcDoc, FileType srcType, long srcTypeHint,
- const FSSpec* dstDoc, FileType dstType, long dstTypeHint)
- {
- #pragma unused(self)
- #pragma unused(progressRefNum)
- #pragma unused(srcDoc)
- #pragma unused(srcType)
- #pragma unused(srcTypeHint)
- #pragma unused(dstDoc)
- #pragma unused(dstType)
- #pragma unused(dstTypeHint)
-
- OSErr myErr = noErr;
- short srcRefNum, dstRefNum;
- char copyBuffer[512];
- long copyBufferSize;
- Handle myAdvert;
- short myShort;
-
- copyBufferSize = 512;
-
- myErr = FSpOpenDF( srcDoc, fsRdPerm, &srcRefNum );
- if( myErr == noErr ){
- myErr = FSpOpenDF( dstDoc, fsRdWrPerm, &dstRefNum );
- if( myErr == noErr ){
- myShort = OpenComponentResFile((Component)self);
- myAdvert = Get1Resource('PICT', kProgressAdvertisement);
- if(myAdvert != nil){
- DetachResource(myAdvert);
- SetTranslationAdvertisement(progressRefNum,(PicHandle) myAdvert);
- }
- else {
- SetTranslationAdvertisement(progressRefNum, nil);
- }
- myErr = CloseComponentResFile(myShort);
- myErr = CopyFork(*srcDoc, srcRefNum, dstRefNum, ©Buffer, copyBufferSize,progressRefNum );
-
- }
- }
- FSClose(srcRefNum);
- FSClose(dstRefNum);
-
-
- return myErr;
- }
-
- //___________________________________________________________________________________________________________
- //
- // DoGetTranslatedFilename
- //
- //
- //
- pascal ComponentResult DoGetTranslatedFilename(ComponentInstance self,
- FileType dstType,
- long dstTypeHint,
- FSSpec* theDocument)
- {
- #pragma unused(self);
- #pragma unused(dstType);
- #pragma unused(dstTypeHint);
- #pragma unused(theDocument);
- Str63 theString;
- FSSpec mySpec;
- OSErr myErr = noErr;
- short i = 0;
-
-
-
- BlockMove( theDocument->name, theString, 64);
- theDocument->name[0] = theDocument->name[0] + 3;
- theDocument->name[1] = 'U';
- theDocument->name[2] = 'U';
- theDocument->name[3] = 'P';
-
- BlockMove( theString + 1, theDocument->name + 4, 60);
-
- myErr = FSMakeFSSpec( theDocument->vRefNum, theDocument->parID, theDocument->name, &mySpec);
- //quick and dirty way of naming, some error checking should be done so no illegal characters are used
- while( myErr != fnfErr ){
- theDocument->name[3] = (char)(theDocument->name[3]) + 1;
- myErr = FSMakeFSSpec( theDocument->vRefNum, theDocument->parID, theDocument->name, &mySpec);
- }
-
- if( myErr == fnfErr ){
- myErr = noErr;
- }
-
- return myErr;
-
- }
- //
- //
- // Took this function out of MoreFiles and modified it a bit
- // MoreFiles can be found on the ToolChest edition of the Developer CDs
- //
- pascal OSErr CopyFork(FSSpec srcSpec, short srcRefNum,
- short dstRefNum,
- void *copyBufferPtr,
- long copyBufferSize, TranslationRefNum progressRefNum)
- {
- ParamBlockRec srcPB;
- ParamBlockRec dstPB;
- OSErr srcError;
- OSErr dstError;
- Boolean canceled = false;
- short myPercent = 0;
- short yourPercent;
- unsigned short numBlocks;
- long myBlockSize;
-
- char* currentCharacter;
- char* lastCharacter;
-
- if ( (copyBufferPtr == NULL) || (copyBufferSize == 0) )
- return ( paramErr );
-
- srcPB.ioParam.ioRefNum = srcRefNum;
- dstPB.ioParam.ioRefNum = dstRefNum;
-
- // preallocate the destination fork and
- // ensure the destination fork's EOF is correct after the copy
- srcError = PBGetEOFSync(&srcPB);
- if ( srcError != noErr )
- return ( srcError );
- dstPB.ioParam.ioMisc = srcPB.ioParam.ioMisc;
- dstError = PBSetEOFSync(&dstPB);
- if ( dstError != noErr )
- return ( dstError );
-
-
-
- // If copyBufferSize is greater than 512 bytes, make it a multiple of 512 bytes
- // This will make writes on local volumes faster
-
- myBlockSize = ((copyBufferSize >= 512) && (copyBufferSize % 512)) ?
- (copyBufferSize / 512) * 512 :
- (copyBufferSize);
-
- //need to know the size of the file to give user feedback
- //thru the progress dialog box. So here we count the blocks
-
- srcError = CountTheBlocks(srcSpec.vRefNum,
- srcSpec.parID,
- srcSpec.name, myBlockSize,
- &numBlocks);
- if( srcError == noErr ){
- myPercent = numBlocks;
- }
- else{
- myPercent = 0;
- }
-
- // reset source fork's mark
- srcPB.ioParam.ioPosMode = fsFromStart;
- srcPB.ioParam.ioPosOffset = 0;
- srcError = PBSetFPosSync(&srcPB);
- if ( srcError != noErr )
- return ( srcError );
-
- // reset destination fork's mark
- dstPB.ioParam.ioPosMode = fsFromStart;
- dstPB.ioParam.ioPosOffset = 0;
- dstError = PBSetFPosSync(&srcPB);
- if ( dstError != noErr )
- return ( dstError );
-
- // set up fields that won't change in the loop
- srcPB.ioParam.ioBuffer = (Ptr)copyBufferPtr;
- srcPB.ioParam.ioPosMode = fsAtMark + 0x0020;// fsAtMark + noCacheBit
- srcPB.ioParam.ioReqCount = myBlockSize;
-
-
-
- dstPB.ioParam.ioBuffer = (Ptr)copyBufferPtr;
- dstPB.ioParam.ioPosMode = fsAtMark + 0x0020;// fsAtMark + noCacheBit
- yourPercent = 0;
- while ( (srcError == noErr) && (dstError == noErr) )
- {
- srcError = PBReadSync(&srcPB);
- dstPB.ioParam.ioReqCount = srcPB.ioParam.ioActCount;
-
- currentCharacter = (char*)copyBufferPtr;
- lastCharacter = currentCharacter + srcPB.ioParam.ioActCount;
-
- while ((currentCharacter <= lastCharacter) && !canceled)
- {
- // Are we in the lower case ASCII range?
- if (('a' <= *currentCharacter) && (*currentCharacter <= 'z'))
- {
- *currentCharacter = (*currentCharacter - ('a' - 'A'));
- }
-
-
- // Next…
- currentCharacter++;
-
- }
-
-
- dstError = PBWriteSync(&dstPB);
- yourPercent++;
- UpdateTranslationProgress(progressRefNum, ((yourPercent * 100)/myPercent) , &canceled);
-
- }
-
- // make sure there were no errors at the destination
- if ( dstError != noErr )
- return ( dstError );
-
- // make sure the only error at the source was eofErr
- if ( srcError != eofErr )
- return ( srcError );
-
- return ( noErr );
- }
- static OSErr CountTheBlocks(short srcVRefNum,
- long srcDirID,
- ConstStr255Param srcName, long theBlockSize,
- unsigned short *numDataBlks)
- {
- HParamBlockRec pb;
- OSErr error;
- unsigned short srcDataBlks;
-
-
- // get the size of the file's data resource fork
- pb.fileParam.ioNamePtr = (StringPtr)srcName;
- pb.fileParam.ioVRefNum = srcVRefNum;
- pb.fileParam.ioFVersNum = 0;
- pb.fileParam.ioDirID = srcDirID;
- pb.fileParam.ioFDirIndex = 0;
- error = PBHGetFInfoSync(&pb);
- if ( error == noErr )
- {
- // get number of 512-byte blocks needed for data fork
- srcDataBlks = ((unsigned long)pb.fileParam.ioFlLgLen % 512) ?
- (((unsigned long)pb.fileParam.ioFlLgLen >> 9) + 1) :
- ((unsigned long)pb.fileParam.ioFlLgLen >> 9);
- }
-
- *numDataBlks = ( srcDataBlks * 512 )/ theBlockSize;
- return ( error );
- }